/*
 * SelectableChannel.h
 *
 *  Created on: Jul 14, 2016
 *      Author: Lucifer
 */

#ifndef BFX_SELECTABLECHANNEL_H_
#define BFX_SELECTABLECHANNEL_H_

#include "./RCObject.h"
#include "./Socket.h"
#include <boost/thread.hpp>
#include <boost/function.hpp>

namespace BFX {

class SelectionKey;
class Selector;

typedef void (*SelectCallback)(SelectionKey* key);

class SelectableChannel: public RCObject {
public:
	SelectableChannel() {
		_closed = false;
		_keys = NULL;
		_keyCapacity = _keyCount = 0;
	}
	virtual ~SelectableChannel() {
		BFX_ASSERT(_closed);
	}

	bool isClosed() const {
		return !_closed;
	}
	void close();

	SelectionKey* registerKey(Selector* sel, int ops, SelectCallback callback);

	/// Returns an operation set identifying this channel's supported operations.
	virtual int getValidOps() const = 0;
	/// Sets the ready operation set to specified selection key.
	virtual bool setReadyOps(int ops, SelectionKey* key) = 0;

	virtual fildes_t getDescriptor() const = 0;

protected:
	void setToOpen();
	virtual void closeImpl();

	// Internal key array operations.
	friend class Selector;
	SelectionKey* findKey(Selector* sel);
	void addKey(SelectionKey* key);
	void removeKey(SelectionKey* key);

private:
	bool _closed;
	/// Keys that have been created by registering this channel with selectors.
	/// They are saved because if this channel is closed the keys must be unregistered.
	SelectionKey** _keys;
	size_t _keyCapacity;
	size_t _keyCount;
	boost::recursive_mutex _keyLock;
};

} /* namespace BFX */

#endif /* BFX_SELECTABLECHANNEL_H_ */
